import 'dotenv/config';
import {
  ClassSerializerInterceptor,
  ConsoleLogger,
  ValidationPipe,
  VersioningType,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { NestFactory, Reflector } from '@nestjs/core';

import { useContainer } from 'class-validator';
import { AppModule } from './app.module';
import validationOptions from './utils/validation-options';
import { AllConfigType } from './config/config.type';
import { ResolvePromisesInterceptor } from './utils/serializer.interceptor';
import { createLogger } from '@/common/logger/common';
import { initSwagger } from '@/common/swagger.module';
import { LoggerMiddleware } from '@/common/logger/logger.middleware';
import registerAs from '@/config/app.config';
import { AppConfig, LOG_LEVELS } from './config/app-config.type';
import cookieParser from 'cookie-parser';
// import helmet from 'helmet';
async function bootstrap() {
  const logLevel = (registerAs() as AppConfig).logLevel as LOG_LEVELS;

  const logger = createLogger('app');
  const app = await NestFactory.create(AppModule, {
    cors: true,
    logger: new ConsoleLogger({
      prefix: 'admin',
      logLevels: [logLevel],
    }),
  });
  app.use(cookieParser());
  // 头部设置
  // app.use(helmet());
  // 全局注入验证
  useContainer(app.select(AppModule), { fallbackOnErrors: true });
  const configService = app.get(ConfigService<AllConfigType>);
  // 启用应用关闭钩子
  app.enableShutdownHooks();
  // 跨域
  app.enableCors();
  // api 前缀
  app.setGlobalPrefix(
    configService.getOrThrow('app.apiPrefix', { infer: true }),
    {
      exclude: ['/'],
    },
  );
  // API 版本
  app.enableVersioning({
    type: VersioningType.URI,
  });
  // 管道验证
  app.useGlobalPipes(new ValidationPipe(validationOptions));
  // 全局拦截器
  app.useGlobalInterceptors(
    // ResolvePromisesInterceptor is used to resolve promises in responses because class-transformer can't do it
    // https://github.com/typestack/class-transformer/issues/549
    new ResolvePromisesInterceptor(),
    new ClassSerializerInterceptor(app.get(Reflector)),
  );
  if ([LOG_LEVELS.debug].includes(logLevel)) {
    app.use(LoggerMiddleware);
  }

  //swagger
  initSwagger(app);
  const port = configService.getOrThrow('app.port', { infer: true });
  await app.listen(port);
  logger.log(`服务=>http://localhost:${port}`);
}
void bootstrap();
